/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2020-2021.
 * Description: self-decompressed misc file
 * Author: yanbo <joey.yanbo@huawei.com>
 * Create: 2020-11-19
 */
#include <linux/compiler.h>
#include <linux/types.h>
#include <linux/linkage.h>
#include <linux/string.h>
#include <linux/hal/watchdog.h>
#include "base.h"
#include "misc.h"
#include "libfdt.h"


unsigned char *output_data;

unsigned long free_mem_ptr;
unsigned long free_mem_end_ptr;

#ifndef arch_error
#define arch_error(x)
#endif

#ifdef CONFIG_RTOS_CFI_MODE_ENFORCING
/*
 * rtos_hcfi_logger - a routine used for HCFI when checking tag of target symbol
 * failed in enforcing mode.
 * this routine does nothing, just ignoring tag inconsistencies, since this
 * function can only be triggered in decompressing the kernel image stage, that
 * is almost safe.
 * it is a temporary solution currently.
 * in the future, the HCFI feature will be improved on this portion.
 */
void rtos_hcfi_report(void) {}
#endif /* CONFIG_RTOS_CFI_MODE_ENFORCING */

#ifdef CONFIG_RTOS_CFI_MODE_PERMISSIVE
/*
 * rtos_hcfi_logger - a routine used for HCFI when checking tag of target symbol
 * failed in permissive mode.
 * this routine does nothing, just ignoring tag inconsistencies, since this
 * function can only be triggered in decompressing the kernel image stage, that
 * is almost safe.
 * it is a temporary solution currently.
 * in the future, the HCFI feature will be improved on this portion.
 */
void rtos_hcfi_logger(void) {}
#endif /* CONFIG_RTOS_CFI_MODE_PERMISSIVE */

void error(char *x)
{
	arch_error(x);

	putstr("\n\n");
	putstr(x);
	putstr("\n\n -- System halted");
	/* Halt */
	while (1)
		;
}

const unsigned long __stack_chk_guard = 0x000a0dff;

void __stack_chk_fail(void)
{
	error("stack-protector: Kernel stack is corrupted\n");
}

void
decompress_kernel(unsigned long output_start, unsigned long free_mem_ptr_p,
		unsigned long free_mem_ptr_end_p,
		int arch_id)
{
	int ret;

	output_data		= (unsigned char *)output_start;
	free_mem_ptr		= free_mem_ptr_p;
	free_mem_end_ptr	= free_mem_ptr_end_p;

#ifdef CONFIG_RTOS_HAL_SELFDECOMPRESS_MAP_PHYS_ADDR_ABOVE_4G
	hwdog_simple_init((void *)dtb_addr, true, map_hwdog_addr_above_4G,
		unmap_hwdog_addr_above_4G);
#else
	hwdog_simple_init((void *)dtb_addr, true, NULL, NULL);
#endif

#ifdef CONFIG_RTOS_HAL_DEBUG_LL
	find_debugll((void *)dtb_addr);
#endif

	find_early_print_disabled((void *)dtb_addr);
#ifdef CONFIG_SECURITY_FOB_BOOT_PRINT
	putstr("Uncompressing...");
#else
	putstr("Uncompressing Linux...");
#endif
	ret = do_decompress(input_data, input_data_end - input_data,
			    output_data, error);
	if (ret) {
		error("decompressor returned an error");
	} else {
		hwdog_feed();
#ifdef CONFIG_SECURITY_FOB_BOOT_PRINT
		putstr(" done, booting...\n");
#else
		putstr(" done, booting the 5.x kernel.\n");
#endif
	}
}

void fortify_panic(const char *name)
{
	error("detected buffer overflow");
}
